package com.tianquan.miracle.postprocessor;

import com.tianquan.miracle.util.MiracleUtils;
import jakarta.annotation.Resource;

import java.lang.reflect.Field;

/**
 * @Author: tianquan
 * @date: 2024-10-17  18:28
 * @Description: 解析Resource 用于在 bean 初始化后注入带有 @Resource 注解的字段。
 */
public class ResourceBeanPostProcessor implements InjectBeanPostProcessor {

    /**
     * 注入带有 @Resource 注解的字段。
     *
     * @param bean 当前处理的 bean 实例。
     */
    @Override
    public void inject(Object bean) {
        // 获取 bean 的类
        Class<?> aClass = bean.getClass();
        // 遍历类中的所有字段
        for (Field field : aClass.getDeclaredFields()) {
            // 获取字段上的 @Resource 注解
            Resource resource = field.getAnnotation(Resource.class);
            // 如果字段没有 @Resource 注解，则跳过当前字段
            if (resource == null) {
                continue;
            }
            // 设置字段可访问，以绕过访问控制
            field.setAccessible(true);
            try {
                // 优先根据名称注入
                Object value = MiracleUtils.getBean(field.getName());
                if (value == null) {
                    // 根据类型注入
                    Class<?> fieldClass = field.getClass();
                    value = MiracleUtils.getBean(fieldClass);
                    // 如果根据名称和类型都没有找到对应的 bean，则抛出异常
                    if (value == null) {
                        throw new RuntimeException("can not find bean is " + field.getName());
                    }
                }
                // 注入
                field.set(bean, value);
            } catch (Exception e) {
                // 捕获并重新抛出异常
                throw new RuntimeException(e);
            }
        }
    }

}

